#include "TcpServer.hpp"
#include <memory>
#include <iostream>
#include "Protocol.hpp"
#include "Calculator.hpp"
#include "Log.hpp"
#include "Daemon.hpp"
using namespace LogModule;
// 全局变量，用于计算模块的实例化
//Calculator gcal;
using cal_fun = std::function<Response(const Request&)>;
// package 一定会有完整的报文吗 不一定
// 不完整，就继续读
// 完整 -> 提取 -> 反序列化 -> Request -> 计算模块，进行处理
// 一次处理一个请求
// std::string Entry(std::string &package)
// {
//     // 1,判断报文的完整性
//     std::string message;//获取一个报文中的有效数据
//     bool rs = Decode(package, &message);//我们通过Decode函数的逻辑，来判断报文的完整性
//     if(!rs || message.empty()) return std::string();//如果报文不完整，或者解码失败了，直接返回空串
//     //走到这里，就表示一定读到了一个完整的报文
//     // 2,反序列化，message一定是一个曾经被序列化的request
//     Request req;
//     if(!req.Deserialize(message)) return std::string();//如果反序列化失败了，直接返回空串

//     // 3,计算
//     Response resp = gcal.Execute(req);

//     // 4,序列化
//     std::string resptr;
//     resp.Serialize(resptr);

//     //序列化完以后，不能立即返回，还要添加长度报头
//     //5，添加长度报头字段
//     Encode(resptr);
//     return resptr;
// }

class Parse // 封装的计算模块
{
public:
    Parse(cal_fun cal) : _cal(cal) {}
    // 一次处理多个请求
    std::string Entry(std::string &package)
    {
        // 1,判断报文的完整性
        std::string message; // 获取一个报文中的有效数据
        std::string respstr;
        while (Decode(package, &message)) // 我们通过Decode函数的逻辑，来判断报文的完整性
        {
            if (message.empty())
                break;
            // 走到这里，就表示一定读到了一个完整的报文
            //  2,反序列化，message一定是一个曾经被序列化的request
            Request req;
            if (!req.Deserialize(message))
                break;
            
            // 3,计算
            Response resp = _cal(req);

            // 4,序列化
            std::string res;
            resp.Serialize(res);

            // 5，添加长度报头字段
            Encode(res);
            // 6,拼接应答
            respstr += res;
        }
        return respstr;
    }
private:
    cal_fun _cal;
};
int main()
{
    ENABLE_FILE_LOG();
    //Daemon(false, false);
    // 1,计算模块
    Calculator mycal;
    // 2,解析对象
    //Parse myparse(std::bind(&Calculator::Execute, &mycal, std::placeholders::_1));
    Parse myparse([&mycal](const Request& req){ return mycal.Execute(req); });
    // TcpServer 只负责进行IO
    std::unique_ptr<TcpServer> tsvr = std::make_unique<TcpServer>([&myparse](std::string &package){return myparse.Entry(package);} );
    tsvr->InitServer();
    tsvr->Start();
    return 0;
}